<template>
    <div id="MainChart">
    </div>
</template>
<script>
import * as d3 from 'd3';
import data from './data.json';
// import { config } from 'vue/types/umd';
// import { set } from 'vue/types/umd';
// import func from '../../vue-temp/vue-editor-bridge';

function dataLeftCompleting(value){
    return parseInt(value) < 10 ? "0" + value : value;
} 
export default {
    name:'MainChart',
    props:{
        /*
        date:{
            type:String,
            default:"2020-02-01"
        },*/
        colormap:Object,
        // value1:Number,
        config: Object,
        message:Function,
    },
    data(){
        return {
            //起始日期
            initDate: "2020-02-01",
            lastDate: "2020-06-22",
            date:"2020-02-01",
            dates: null,
            datesCount: 0,
            tmpCurDate: null,
            tmpEndDate: null,
            xdomain:100.,
            ydomain:100.,
            sumDeath: 0.,
            sumCase: 0.,
            //图的长和宽，也应当是坐标轴的长和宽
            gwidth:1400,
            gheight:600,
            //坐标轴的长和宽
            height:300,
            width:1080,
            padding:{
                left:40,
                up:40,
                buttom:40,
                right:40,
            },
            xscale:null,
            xscaleLog:null,
            yscale:null,
            yscaleLog:null,
            svg: null,
            duration: 40,
            durationSlider: 1000,
            move: true,
            iter: null,
            iterSlider: null,
            chartEnter: null,
            text: null,
            slider: null,
            ellscale: 200,
            maxellr: 25,
            minellr: 5,
            mindisplay: 50,
            sliderVal: 0,
            ratio: 1.,
            data: data
        }
    },
    watch: {
        config: {
            handler(newVal, oldVal) {
                clearInterval(this.iter);
                console.log(newVal);
                console.log(oldVal);
                console.log("!!"+this.config.axis);
                // this.sliderVal = val;
                this.ratio = this.config.times;
                this.tmpCurDate = new Date(this.initDate);
                for (let i = 0; i != this.config.value1; ++i) {
                    this.iterateDatenoUpdate();
                }
                this.updateData();
            }, 
            deep: true
        },
    },
    mounted(){
        this.initChart();
    },
    methods:{
        //计算x轴值域,新增确认
        updateXdomain(){
            const itemx = this.config.x;
            const tmp=this.data[this.date].map((item, i)=>{return (i == 0 || !(itemx in item)) ? 0 : Number(item[itemx])});
            const maxN = Math.max.apply(null, tmp);
            // this.xdomain=Math.max(this.xdomain, maxN);
            this.xdomain=Math.max(maxN, 100);
        },
        // 新增死亡
        updateYdomain(){
            const itemy = this.config.y;
            const tmp=this.data[this.date].map((item, i)=>{return (i == 0 || !(itemy in item)) ? 0 :  Number(item[itemy])});
            const maxN = Math.max.apply(null, tmp);
            // this.ydomain=Math.max(this.ydomain, maxN);
            this.ydomain=Math.max(maxN, 100);
        },
        updateData(){
            this.updateXdomain();
            this.updateYdomain();
            this.updateSumTotal();
            this.updateChart();

            this.$emit("recv",this.data[this.date][0]);
        },
        updateSumTotal() {
            if (this.config.rx in this.data[this.date][0])
                this.sumCase = Number(this.data[this.date][0][this.config.rx]);
            if (this.config.ry in this.data[this.date][0])
                this.sumDeath = Number(this.data[this.date][0][this.config.ry]);
        },
        updateChart() {
            // const xscale = d3.scaleLinear().domain([0,this.xdomain]).rangeRound([0,this.gwidth]);
            // const yscale = d3.scaleLinear().domain([0,this.ydomain]).rangeRound([this.gheight,0]).nice();
            const xscale = d3.scaleLinear().domain([0,this.xdomain]).rangeRound([0,this.gwidth]);
            const xscaleLog = d3.scaleSymlog().domain([0,this.xdomain]).range([0,this.gwidth]);
            const yscale = d3.scaleLinear().domain([0,this.ydomain]).rangeRound([this.gheight,0]).nice();
            const yscaleLog = d3.scaleSymlog().domain([0,this.ydomain]).range([this.gheight,0]);
            const scaleMode = this.config.axis;
            const xaxisUpdate = this.xAxis;
            const yaxisUpdate = this.yAxis;

            if (scaleMode == 'linear') {
                xaxisUpdate.transition()
                            .call(d3.axisBottom(xscale));
                yaxisUpdate.transition()
                            .call(d3.axisLeft(yscale).ticks(6));
            }
            else {
                xaxisUpdate.transition()
                            .call(d3.axisBottom(xscaleLog));
                yaxisUpdate.transition()
                            .call(d3.axisLeft(yscaleLog).ticks(6));
            }
            
            const circleUpdate = this.chart;
            const textUpdate = this.text;
            const sumDeath = this.sumDeath;
            const sumCase = this.sumCase;
            const colormap = this.config.colormap;
            const ellscale = this.ellscale;
            const maxellr = this.maxellr;
            const minellr = this.minellr;
            const itemx = this.config.x;
            const itemy = this.config.y;
            const itemrx = this.config.rx;
            const itemry = this.config.ry;
            const mindisplay = this.mindisplay;
            const ratio = this.ratio;
            circleUpdate
                .data(this.data[this.date])
                .transition()
                .attr("rx", function(item, i) {
                    if (i == 0)
                        return 0;
                    else if(itemrx in item)
                        return Math.max(minellr, 
                                Math.min(Number(item[itemrx])*ellscale/sumCase, maxellr))*ratio;
                    else
                        return 0;
                    })
                .attr("ry", function(item, i) {
                    if (i == 0)
                        return 0;
                    else if(itemry in item)
                        return Math.max(minellr, 
                                Math.min(Number(item[itemry])*ellscale/sumDeath, maxellr))*ratio;
                    else
                        return 0;
                    })
                .attr("cx",function(item, i){
                    if (scaleMode == 'linear') {
                        if (i == 0)
                            return xscale(0);
                        else if(itemx in item)
                            return xscale(item[itemx]);
                        else
                            return xscale(0);
                    }
                    else {
                        if (i == 0)
                            return xscaleLog(0);
                        else if(itemx in item)
                            return xscaleLog(item[itemx]);
                        else
                            return xscaleLog(0);
                    }
                    })
                .attr("cy",function(item, i){
                    if (scaleMode == 'linear') {
                        if (i == 0)
                            return yscale(0);
                        else if(itemy in item)
                            return yscale(item[itemy]);
                        else
                            return yscale(0);
                    }
                    else {
                        if (i == 0)
                            return yscaleLog(0);
                        else if(itemy in item)
                            return yscaleLog(item[itemy]);
                        else
                            return yscaleLog(0);
                    }
                    })
                .attr("fill-opacity", function(item, i) {
                    let px = xscale(0)
                    let py = yscale(0)
                    if (scaleMode == 'linear') {
                        if (i > 0 && itemx in item)
                            px = xscale(item[itemx]);
                        if (i > 0 && itemy in item)
                            py = yscale(item[itemy]);
                    }
                    else {
                        if (i > 0 && itemx in item)
                            px = xscaleLog(item[itemx]);
                        if (i > 0 && itemy in item)
                            py = yscaleLog(item[itemy]);
                    }
                    if (scaleMode == 'linear') {
                        if (Math.abs(Number(px)-Number(xscale(0))) < mindisplay
                            || Math.abs(Number(py)-Number(yscale(0))) < mindisplay) {
                            return 0.8 * Math.min(
                                Math.abs(Number(px)-Number(xscale(0))), 
                                Math.abs(Number(py)-Number(yscale(0)))) 
                                / mindisplay;
                        }
                    }
                    else { 
                        if (Math.abs(Number(px)-Number(xscaleLog(0))) < mindisplay
                            || Math.abs(Number(py)-Number(yscaleLog(0))) < mindisplay) {
                            return 0.8 * Math.min(
                                Math.abs(Number(px)-Number(xscaleLog(0))), 
                                Math.abs(Number(py)-Number(yscaleLog(0)))) 
                                / mindisplay;
                        }
                    }
                    return 0.8;
                })
                .attr("fill", function(item) {
                    if (colormap[item["国家地区"]]) {
                        return colormap[item["国家地区"]];
                    }
                    else
                        return "grey";
                });
            this.tooltip.data(this.data[this.date]).text(function(item) {return item["国家地区"]+"\n累计确诊:"+item["累计确诊"]+"\n累计死亡:"+item["累计死亡"];});
            textUpdate
                .data(this.data[this.date])
                .transition()
                .attr("x",function(item, i){
                    if (scaleMode == 'linear') {
                        if (i == 0)
                            return xscale(0);
                        else if(itemx in item)
                            return xscale(item[itemx]);
                        else
                            return xscale(0);
                    }
                    else {
                        if (i == 0)
                            return xscaleLog(0);
                        else if(itemx in item)
                            return xscaleLog(item[itemx]);
                        else
                            return xscaleLog(0);
                    }
                    })
                .attr("y",function(item, i){
                    if (scaleMode == 'linear') {
                        if (i == 0)
                            return yscale(0);
                        else if(itemy in item)
                            return yscale(item[itemy]);
                        else
                            return yscale(0);
                    }
                    else {
                        if (i == 0)
                            return yscaleLog(0);
                        else if(itemy in item)
                            return yscaleLog(item[itemy]);
                        else
                            return yscaleLog(0);
                    }
                    })
                .attr("dx", function(item, i) {
                    if (i == 0)
                        return 1;
                    else if(itemrx in item)
                        return 1+Math.min(Number(item[itemrx])*ellscale/sumCase, 20)*ratio;
                    else
                        return 1;
                    })
                .attr("font-size", "8px")
                .attr("fill-opacity", function(item, i) {
                    let px = xscale(0)
                    let py = yscale(0)
                    if (scaleMode == 'linear') {
                        if (i > 0 && itemx in item)
                            px = xscale(item[itemx]);
                        if (i > 0 && itemy in item)
                            py = yscale(item[itemy]);
                    }
                    else {
                        if (i > 0 && itemx in item)
                            px = xscaleLog(item[itemx]);
                        if (i > 0 && itemy in item)
                            py = yscaleLog(item[itemy]);
                    }
                    if (scaleMode == 'linear') {
                        if (Math.abs(Number(px)-Number(xscale(0))) < mindisplay
                            || Math.abs(Number(py)-Number(yscale(0))) < mindisplay) {
                            return 0.8 * Math.min(
                                Math.abs(Number(px)-Number(xscale(0))), 
                                Math.abs(Number(py)-Number(yscale(0)))) 
                                / mindisplay;
                        }
                    }
                    else { 
                        if (Math.abs(Number(px)-Number(xscaleLog(0))) < mindisplay
                            || Math.abs(Number(py)-Number(yscaleLog(0))) < mindisplay) {
                            return 0.8 * Math.min(
                                Math.abs(Number(px)-Number(xscaleLog(0))), 
                                Math.abs(Number(py)-Number(yscaleLog(0)))) 
                                / mindisplay;
                        }
                    }
                    return 0.8;
                })
                .text(function(item) {return item["国家地区"];});
        },
        iterateDatenoUpdate() {
            this.tmpCurDate.setDate(this.tmpCurDate.getDate()+1);
            this.date = `${this.tmpCurDate.getFullYear()}-${dataLeftCompleting(this.tmpCurDate.getMonth()+1)}-${dataLeftCompleting(this.tmpCurDate.getDate())}`;
        }, 
        iterateDate() {
            if (this.tmpCurDate.getTime() != this.tmpEndDate.getTime()) {
                this.tmpCurDate.setDate(this.tmpCurDate.getDate()+1);
                this.date = `${this.tmpCurDate.getFullYear()}-${dataLeftCompleting(this.tmpCurDate.getMonth()+1)}-${dataLeftCompleting(this.tmpCurDate.getDate())}`;
                this.updateData();
            }
            else {
                this.move = false;
                clearInterval(this.iter);
            }
        },
        generateDates() {
            const endDate = new Date(this.lastDate);
            this.dates = [];
            for (let tmpDate = new Date(this.initDate);
                tmpDate.getTime() != endDate.getTime();) {
                tmpDate.setDate(tmpDate.getDate()+1);
                const tmpdate = `${tmpDate.getFullYear()}-${dataLeftCompleting(tmpDate.getMonth()+1)}-${dataLeftCompleting(tmpDate.getDate())}`;
                this.datesCount = this.dates.push(tmpdate);
            }
        },
        checkSlider() {
        }, 
        initChart(){
            this.sumDeath=Number(this.data[this.date][0][this.config.rx]),
            this.sumCase=Number(this.data[this.date][0][this.config.ry]),
            this.generateDates();
            this.updateXdomain();
            this.updateYdomain();
            this.updateSumTotal();
            //this.nameArray = this.data.map((item)=> { return item.name;});
            const xscale = d3.scaleLinear().domain([0,this.xdomain]).rangeRound([0,this.gwidth]);
            const xscaleLog = d3.scaleSymlog().domain([0,this.xdomain]).rangeRound([0,this.gwidth]);
            const yscale = d3.scaleLinear().domain([0,this.ydomain]).rangeRound([this.gheight,0]).nice();
            const yscaleLog = d3.scaleSymlog().domain([0,this.ydomain]).rangeRound([this.gheight,0]).nice();
            const scaleMode = this.config.axis;
            this.xscale=xscale;
            this.yscale=yscale;
            this.xscaleLog=xscaleLog;
            this.yscaleLog=yscaleLog;
            d3.select('#MainChart')
                .style('width','100%')
                .style('height','100%');
            
            //根元素挂载画布
            this.svg=d3.select('#MainChart').append('svg')
                .attr('width',`${this.gwidth+this.padding.left+this.padding.right}`)
                .attr('height',`${this.gheight+this.padding.up+this.padding.buttom}`);
            
            this.gwidth=d3.select('#MainChart').node().getBoundingClientRect().width-this.padding.left-this.padding.right;

            // 添加g标签 
            this.graph = this.svg.append('g')
                        .attr('class','chart')  // 图表部分
                        .attr('transform',`translate(${this.padding.left},${this.padding.up})`);
            this.xAxis=this.graph.append('g')
                    .attr('class','xaxis')
                    .attr('transform',`translate(0, ${this.gheight})`)
                    .call(d3.axisBottom(scaleMode == 'linear' ? this.xscale : this.xscaleLog))
                    .attr('font-weight','blod')
                    .attr('font-size',13);
                    
            this.yAxis=this.graph.append('g')
                    .attr('class','yaxis')
                    .call(d3.axisLeft(scaleMode == 'linear' ? this.yscale : this.yscaleLog).ticks(6));
            /*
            this.xAxis.selectAll('.tick')
                    .select('line')
                    .attr('class', 'axis-tick');  // x轴刻度
            this.xAxis.selectAll('.tick')
                    .select('text')
                    .attr('class', 'axis-label');  // x轴标签
                    */
            this.chartEnter = this.graph.selectAll("ellipse")
                    .data(this.data[this.date])
                    .enter()
                    .append("g");
            const sumDeath = this.sumDeath;
            const sumCase = this.sumCase;
            const ellscale = this.ellscale;
            const maxellr = this.maxellr;
            const minellr = this.minellr;
            const itemx = this.config.x;
            const itemy = this.config.y;
            const itemrx = this.config.rx;
            const itemry = this.config.ry;
            const mindisplay = this.mindisplay;
            const ratio = this.ratio;
            this.chart = this.chartEnter
                    .append("ellipse")
                    .attr("rx", function(item, i) {
                        if (i == 0)
                            return 0;
                        else if(itemrx in item)
                            return Math.max(minellr, 
                                    Math.min(Number(item[itemrx])*ellscale/sumCase, maxellr))*ratio;
                        else
                            return 0;
                        })
                    .attr("ry", function(item, i) {
                        if (i == 0)
                            return 0;
                        else if(itemry in item)
                            return Math.max(minellr,
                                    Math.min(Number(item[itemry])*ellscale/sumDeath, maxellr))*ratio;
                        else
                            return 0;
                        })
                    .attr("fill-opacity", function(item, i) {
                        let px = xscale(0)
                        let py = yscale(0)
                        if (scaleMode == 'linear') {
                            if (i > 0 && itemx in item)
                                px = xscale(item[itemx]);
                            if (i > 0 && itemy in item)
                                py = yscale(item[itemy]);
                        }
                        else {
                            if (i > 0 && itemx in item)
                                px = xscaleLog(item[itemx]);
                            if (i > 0 && itemy in item)
                                py = yscaleLog(item[itemy]);
                        }
                        if (scaleMode == 'linear') {
                            if (Math.abs(Number(px)-Number(xscale(0))) < mindisplay
                                || Math.abs(Number(py)-Number(yscale(0))) < mindisplay) {
                                return 0.8 * Math.min(
                                    Math.abs(Number(px)-Number(xscale(0))), 
                                    Math.abs(Number(py)-Number(yscale(0)))) 
                                    / mindisplay;
                            }
                        }
                        else { 
                            if (Math.abs(Number(px)-Number(xscaleLog(0))) < mindisplay
                                || Math.abs(Number(py)-Number(yscaleLog(0))) < mindisplay) {
                                return 0.8 * Math.min(
                                    Math.abs(Number(px)-Number(xscaleLog(0))), 
                                    Math.abs(Number(py)-Number(yscaleLog(0)))) 
                                    / mindisplay;
                            }
                        }
                        return 0.8;
                        })
                    .attr("cx",function(item, i){
                        if (scaleMode == 'linear') {
                            if (i == 0)
                                return xscale(0);
                            else if(itemx in item)
                                return xscale(item[itemx]);
                            else
                                return xscale(0);
                        }
                        else {
                            if (i == 0)
                                return xscaleLog(0);
                            else if(itemx in item)
                                return xscaleLog(item[itemx]);
                            else
                                return xscaleLog(0);
                        }
                        })
                    .attr("cy",function(item, i){
                        if (scaleMode == 'linear') {
                            if (i == 0)
                                return yscale(0);
                            else if(itemy in item)
                                return yscale(item[itemy]);
                            else
                                return yscale(0);
                        }
                        else {
                            if (i == 0)
                                return yscaleLog(0);
                            else if(itemy in item)
                                return yscaleLog(item[itemy]);
                            else
                                return yscaleLog(0);
                        }
                    });
            this.tooltip = this.chartEnter.append('title').text(function(item) {return item["国家地区"]+"\n累计确诊:"+item["累计确诊"]+"\n累计死亡:"+item["累计死亡"];});
            this.text = this.chartEnter.append("text")
                    .attr("class", "ctext")
                    .attr("x",function(item, i){
                        if (scaleMode == 'linear') {
                            if (i == 0)
                                return xscale(0);
                            else if(itemx in item)
                                return xscale(item[itemx]);
                            else
                                return xscale(0);
                        }
                        else {
                            if (i == 0)
                                return xscaleLog(0);
                            else if(itemx in item)
                                return xscaleLog(item[itemx]);
                            else
                                return xscaleLog(0);
                        }
                    })
                    .attr("y",function(item, i){
                        if (scaleMode == 'linear') {
                            if (i == 0)
                                return yscale(0);
                            else if(itemy in item)
                                return yscale(item[itemy]);
                            else
                                return yscale(0);
                        }
                        else {
                            if (i == 0)
                                return yscaleLog(0);
                            else if(itemy in item)
                                return yscaleLog(item[itemy]);
                            else
                                return yscaleLog(0);
                        }
                    })
                    .attr("dx", function(item, i) {
                        if (i == 0)
                            return 1;
                        else if(itemrx in item)
                            return 1+Math.min(Number(item[itemrx])*ellscale/sumCase, 20)*ratio;
                        else
                            return 1;
                        })
                    .attr("font-size", "8px")
                    .attr("fill-opacity", function(item, i) {
                        let px = xscale(0)
                        let py = yscale(0)
                        if (scaleMode == 'linear') {
                            if (i > 0 && itemx in item)
                                px = xscale(item[itemx]);
                            if (i > 0 && itemy in item)
                                py = yscale(item[itemy]);
                        }
                        else {
                            if (i > 0 && itemx in item)
                                px = xscaleLog(item[itemx]);
                            if (i > 0 && itemy in item)
                                py = yscaleLog(item[itemy]);
                        }
                        if (scaleMode == 'linear') {
                            if (Math.abs(Number(px)-Number(xscale(0))) < mindisplay
                                || Math.abs(Number(py)-Number(yscale(0))) < mindisplay) {
                                return 0.8 * Math.min(
                                    Math.abs(Number(px)-Number(xscale(0))), 
                                    Math.abs(Number(py)-Number(yscale(0)))) 
                                    / mindisplay;
                            }
                        }
                        else { 
                            if (Math.abs(Number(px)-Number(xscaleLog(0))) < mindisplay
                                || Math.abs(Number(py)-Number(yscaleLog(0))) < mindisplay) {
                                return 0.8 * Math.min(
                                    Math.abs(Number(px)-Number(xscaleLog(0))), 
                                    Math.abs(Number(py)-Number(yscaleLog(0)))) 
                                    / mindisplay;
                            }
                        }
                        return 0.8;
                    })
                    .text(function(item) {return item["国家地区"];});

            // this.updateChart();
            // iteration
            this.tmpCurDate = new Date(this.date);
            this.tmpEndDate = new Date(this.lastDate);
            this.iter = setInterval(this.iterateDate, this.duration);
            // this.iterSlider = setInterval(this.checkSlider, this.durationSlider);
        }
    }
}
</script>